module uart_byte_tx(
	clk,			   // 时钟发生器：system 50MHz
	data,			   // 数据: reg
	send_en,  	   // 使能: reg
	bps_setting, 	// 波特率：reg 
	check_setting, // 校验方式: reg
	rst_n, 			// 复位使能：reg
	
	uart_tx,		   // 串口发送线: system
	tx_done,   		// 一次发送数据完成标志
	uart_state 		// 发送数据状态，发送过程中为1，其它时候为0
);

	input clk;
	input send_en;
	input [2:0] bps_setting; // 0: 4800, 1: 9600, 2: 115200
	input [7:0] data;
	// check_setting高位表示是否开启校验，低位1表示奇校验，0表示偶校验
	input [1:0] check_setting;
	input rst_n;
	
	output reg uart_tx;
	output reg tx_done;
	output reg uart_state; 
	
	
	reg [15:0] div_cnt; 		// 分频计数器计数值
	reg [15:0] div_cnt_max; // 分频计数器最大值，在最大值时输出波特率信号
	reg bps_clk; 				// 波特率信号
	reg [3:0] bps_cnt;  		// 波特率时钟计数器
	reg [3:0] bps_cnt_max;  // 波特率时钟计数器最大值
	
	reg check_switch;  // 校验位开关
	reg check_bit; 	 // 校验位
	reg [7:0] r_data;  // 寄存的数据
	
	localparam START_BIT = 1'b0;
	localparam STOP_BIT = 1'b1;
	
	/********************************************************************************
		波特率发生器
		当clk信号来临时，使能信号send_en为1时，允许设置寄存器，开启波特率发生器
	 ********************************************************************************/
	// 设置uart_state
	always @(posedge clk or negedge rst_n)
	if(!rst_n)
		uart_state <= 1'b0;
	else if(send_en)
		uart_state <= 1'b1;
	else if(bps_cnt == bps_cnt_max)
		uart_state <= 1'b0;
	else
		uart_state <= uart_state;
		
	// 寄存数据内容
	always @(posedge clk or negedge rst_n)
	if (!rst_n)
		r_data <= 8'b0;
	else if (send_en) 
		r_data <= data;
	else
		r_data <= r_data;
	
	// 寄存分频器设置
	always @(posedge clk or negedge rst_n)
	if (!rst_n)
		div_cnt_max <= 16'd5207;
	else if (send_en)
		begin
			case(bps_setting)
				0:div_cnt_max <= 16'd434;    // 115200 bps
				1:div_cnt_max <= 16'd5207;   // 9600 bps 
				2:div_cnt_max <= 16'd10416;  // 4800 bps
				default:div_cnt_max <= 16'd434; // 默认是115200 bps	
			endcase
		end
	
	// 寄存校验位设置
	always @(posedge clk or negedge rst_n)
	if (!rst_n) 
		begin
			check_switch <= 1'b0;
			bps_cnt_max <=  4'd11;
		end
	else if (send_en) 
		begin
			if (check_setting[1] == 1'b0) 
				begin
					check_switch 	<= 	1'b0;
					bps_cnt_max 	<=  	4'd11;
				end
			else 
				begin
					check_switch 	<= 	1'b1;
					bps_cnt_max 	<= 	4'd12;
					check_bit 		<= 	(^data) ^ check_setting[0];
				end
		end
	else
		begin 
			check_switch 	<= 	check_switch;
			bps_cnt_max 	<= 	bps_cnt_max;
			check_bit 		<= 	check_bit;
		end 
	
	
	// 计数器，通过计数器来分频实现波特率发生器
	always @(posedge clk or negedge rst_n)
	if (!rst_n)
		div_cnt <= 16'b0;
	else if (uart_state) // 在发送期间需要开始计数
		begin
			if (div_cnt == div_cnt_max)
				div_cnt <= 16'b0;
			else 
				div_cnt <= div_cnt + 16'b1;
		end
	else						// 其他时候保持为0
		div_cnt <= 16'b0;
	
		
	always @(posedge clk or negedge rst_n)
	if(!rst_n)
		bps_clk 	<= 1'b0;
		else if (div_cnt == 16'd1)  // 只会有整个周期只会有一小段上升信号
		bps_clk 	<=	1'b1;
	else
		bps_clk 	<=	1'b0;
		
	/********************************************************************************
		位计数器，发送哪一位
	*********************************************************************************/
	always @(posedge clk or negedge rst_n)
	if (!rst_n)
		bps_cnt <= 4'd0;
	// 一旦bps_cnt == 7则将bps归0
	else if(bps_cnt == bps_cnt_max)
		bps_cnt <= 4'd0;
	else if(bps_clk)
		bps_cnt <= bps_cnt + 1'b1;
	else
		bps_cnt <= bps_cnt;
	
	
	always @(posedge clk or negedge rst_n)
	if (!rst_n)
		tx_done <= 1'b0;
	else if(bps_cnt == bps_cnt_max)
		tx_done <= 1'b1;
	else
		tx_done <= 1'b0;
	
	// 位发送逻辑
	always @(posedge clk or negedge rst_n)
	if (!rst_n)
		uart_tx <= STOP_BIT;
	else if (uart_state)
		begin
			case (bps_cnt)
				0:uart_tx <= STOP_BIT;
				1:uart_tx <= START_BIT;
				2:uart_tx <= r_data[0];
				3:uart_tx <= r_data[1];
				4:uart_tx <= r_data[2];
				5:uart_tx <= r_data[3];
				6:uart_tx <= r_data[4];
				7:uart_tx <= r_data[5];
				8:uart_tx <= r_data[6];
				9:uart_tx <= r_data[7];
				10:
					begin
						if (check_switch)
							uart_tx <= check_bit;
						else
							uart_tx <= STOP_BIT;
					end
				11:uart_tx <=  STOP_BIT;
			default:uart_tx <= STOP_BIT;
		endcase
		end
	
endmodule
